package com.zenika.zenbinding.client.model;

import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.zenika.zenbinding.client.exception.DataMessage;
import com.zenika.zenbinding.client.feedback.FeedbackManager;
import com.zenika.zenbinding.client.handler.Handler;
import com.zenika.zenbinding.client.renderer.Renderer;

/**
 * A ListModel manages the access to a property of a BusinessObject, the
 * validation and redirect errors of Validation or Conversion to a
 * FeedbackManager. It is used in the case of the property has to be
 * synchronized with a selection of objects in a list. The property could be an
 * Array, a List or an Object.
 * @author Zenika
 */
public class TableModel implements Model, CellModelListener {

	private BusinessObject[] sources;
	private Label[] headers;
	private Renderer[] renderers;
	private FeedbackManager manager;
	private DataMessage currentError;
	private String feedbackId;
	private Handler handler;

	public TableModel(BusinessObject[] sources, Label[] headers, Renderer[] renderers) {
		this.sources = sources;
		this.headers = headers;
		this.renderers = renderers;
	}

	public CellModel getCellModel(int row, int column) {
		CellModel cellModel = new CellModel(row, column, this.sources[row], this.renderers[column]);
		cellModel.addCellModelListener(this);
		return cellModel;
	}

	public boolean hasHeaders() {
		return (this.headers != null) ? true : false;
	}

	public Label getHeader(int column) {
		return this.headers[column];
	}

	public int getRowCount() {
		return this.sources.length;
	}

	public int getColumnCount() {
		return this.renderers.length;
	}

	/**
	 * Notify the entering in error state to the feedback manager.
	 * @param message
	 * @param handler
	 */
	public void fireError(DataMessage message, Handler handler) {
		if (this.manager != null) {
			if (this.feedbackId != null) {
				message.setMessage(message.getMessage() + " : " + this.feedbackId);
			}
			this.manager.enterErrorState(message, handler);
		}
	}

	/**
	 * Notify the leaving of error state to the feedback manager;
	 * @param handler
	 */
	public void fireErrorStop(Handler handler) {
		if (this.manager != null) {
			this.manager.leaveErrorState(handler);
		}
	}

	public void onEnteringErrorState(int row, int column, Handler handler, DataMessage message) {
		// coordinates not used for the moment
		// FIXME debug this
		this.currentError = message;
		this.fireError(message, handler);
	}

	public void onLeavingErrorState(int row, int column, Handler handler) {
		// coordinates not used for the moment
		// FIXME debug this
		this.currentError = null;
		this.fireErrorStop(handler);
	}

	public void setFeedbackManager(FeedbackManager manager) {
		this.manager = manager;
	}

	public void setFeedbackManager(FeedbackManager manager, String feedbackId) {
		this.setFeedbackManager(manager);
		this.feedbackId = feedbackId;
	}

	public void setHandler(Handler handler) {
		this.handler = handler;
	}

	public Handler getHandler() {
		return this.handler;
	}

	public Widget getWidget() {
		return this.handler.getWidget();
	}

	public DataMessage getCurrentValidationState() {
		return this.currentError;
	}

	public DataMessage validate() {
		// FIXME implement this if possible?
		return this.currentError;
	}

}
